#ifndef _TIMER_LIST_CPP_
#define _TIMER_LIST_CPP_

#include "Timer_List.h"

// Default Constructor
template <class TYPE>
Timer_List_Iterator<TYPE>::Timer_List_Iterator (List& lst)
: list_ (lst)
{
	this->first();
}

template <class TYPE>
Timer_List_Iterator<TYPE>::~Timer_List_Iterator (void)
{
}

// Positions the iterator at the node right after the dummy node
template <class TYPE> void
Timer_List_Iterator<TYPE>::first (void)
{
	this->current_node_ = this->list_.get_first();
}

// Positions the iterator at the next node in the Timer Queue
template <class TYPE> void
Timer_List_Iterator<TYPE>::next (void)
{
	// Make sure that if we are at the end, we don't wrap around
	if (! this->isdone())
		this->current_node_ = this->current_node_->get_next ();
	if (this->current_node_  == this->list_.head_)
		this->current_node_ = 0;
}

// Returns true when we are at <head_>
template <class TYPE> int
Timer_List_Iterator<TYPE>::isdone (void) const
{
	return this->current_node_ == 0;
}

// Returns the node at <position_> or 0 if we are at the end
template <class TYPE> Timer_Node<TYPE> *
Timer_List_Iterator<TYPE>::item (void)
{
	if (! this->isdone())
		return this->current_node_;
	return 0;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

// Return our instance of the iterator
template <class TYPE> Timer_Queue_Iterator<TYPE> &
Timer_List<TYPE>::iter (void)
{
	this->iterator_->first ();
	return *this->iterator_;
}

// Create an empty list.
template <class TYPE>
Timer_List<TYPE>::Timer_List (FreeList* fl)
: Base(fl)
, head_ (new Timer_Node<TYPE>)
, id_counter_ (0)
{
	this->head_->set_next (this->head_);
	this->head_->set_prev (this->head_);

	iterator_ = new Iterator(*this);
}


// Checks if list is empty.
template <class TYPE> int
Timer_List<TYPE>::is_empty (void) const
{
	return this->get_first_i() == 0;
}


// Returns earliest time in a non-empty list.
template <class TYPE> unsigned long
Timer_List<TYPE>::earliest_time (void) const
{
	Timer_Node<TYPE>* first = this->get_first_i();
	if (first != 0)
		return first->get_timer_value ();
	return 0;
}

// Remove all remaining items in the list.
template <class TYPE>
Timer_List<TYPE>::~Timer_List (void)
{
	delete iterator_;

	if (!this->is_empty())
	{
		for (Timer_Node<TYPE>* n = this->get_first();
			n != this->head_;
			)
		{
			Timer_Node<TYPE> *next =
				n->get_next ();

			this->free_node (n);

			n = next;
		}
	}

	// delete the dummy node
	delete this->head_;
}

// Reschedule a periodic timer.  This function must be called with the
// lock held.
template <class TYPE> void
Timer_List<TYPE>::reschedule (Timer_Node<TYPE>* n)
{
	this->schedule_i(n, n->get_timer_value());
}


// Insert a new handler that expires at time future_time; if interval
// is > 0, the handler will be reinvoked periodically.
template <class TYPE> long
Timer_List<TYPE>::schedule_i (const TYPE &type,
													   const void *arg,
													   unsigned long future_time,
													   unsigned long interval)
{
	Timer_Node<TYPE>* n = this->alloc_node();

	if (n != 0)
	{
		long id = this->id_counter_++;

		if (id != -1) {
			n->set (type, arg, future_time, interval, id, 0, 0);
			this->schedule_i (n, future_time);
		}
		return id;
	}

	return -1;
}

/// The shared scheduling functionality between schedule() and reschedule()
template <class TYPE> void
Timer_List<TYPE>::schedule_i (Timer_Node<TYPE>* n,
													   unsigned long expire)
{
	if (this->is_empty()) {
		n->set_prev(this->head_);
		n->set_next(this->head_);
		this->head_->set_prev(n);
		this->head_->set_next(n);
		return;
	}

	// We always want to search backwards from the tail of the list, because
	// this minimizes the search in the extreme case when lots of timers are
	// scheduled for exactly the same time, and it also assumes that most of
	// the timers will be scheduled later than existing timers.
	Timer_Node<TYPE>* p = this->head_->get_prev();
	while (p != this->head_ && p->get_timer_value() > expire)
		p = p->get_prev();

	// insert after
	n->set_prev(p);
	n->set_next(p->get_next());
	p->get_next()->set_prev(n);
	p->set_next(n);
}

template <class TYPE>
Timer_Node<TYPE>*
Timer_List<TYPE>::find_node (long timer_id) const
{
	Timer_Node<TYPE>* n = this->get_first_i();
	if (n == 0)
		return 0;

	for (; n != this->head_; n = n->get_next()) {
		if (n->get_timer_id() == timer_id) {
			return n;
		}
	}
	return 0;
}

// Locate and update the inteval on the timer_id
template <class TYPE> int
Timer_List<TYPE>::reset_interval (long timer_id,
														   unsigned long interval)
{
	Timer_Node<TYPE>* n = this->find_node(timer_id);
	if (n != 0) {
		n->set_interval(interval); // The interval will take effect the next time this node is expired.
		return 0;
	}
	return -1;
}

// Locate and remove the single <ACE_Event_Handler> with a value of
// <timer_id> from the timer queue.
template <class TYPE> int
Timer_List<TYPE>::cancel (long timer_id,
												   const void **arg,
												   int skip_close)
{
	Timer_Node<TYPE>* n = this->find_node(timer_id);
	if (n != 0)
	{
		if (arg != 0)
			*arg = n->get_arg ();

		this->cancel_i (n);

		return 1;
	}

	return 0;
}

// Locate and remove all values of <handler> from the timer queue.
template <class TYPE> int
Timer_List<TYPE>::cancel (const TYPE &type, int skip_close)
{
	int num_canceled = 0; // Note : Technically this can overflow.

	if (!this->is_empty ())
	{
		for (Timer_Node<TYPE>* n = this->get_first();
			n != this->head_;
			)
		{
			if (n->get_type() == type) // Note: Typically Type is an ACE_Event_Handler*
			{
				++num_canceled;

				Timer_Node<TYPE>* tmp = n;
				n = n->get_next();

				this->cancel_i (tmp);
			}
			else
			{
				n = n->get_next();
			}
		}
	}

	return num_canceled;
}

template <class TYPE> void
Timer_List<TYPE>::unlink (Timer_Node<TYPE>* n)
{
	n->get_prev()->set_next(n->get_next());
	n->get_next()->set_prev(n->get_prev());
	n->set_prev(0);
	n->set_next(0);
}

/// Shared subset of the two cancel() methods.
template <class TYPE> void
Timer_List<TYPE>::cancel_i (Timer_Node<TYPE>* n)
{
	this->unlink (n);
	this->free_node (n);
}

// Reads the first node on the list and returns it.
template <class TYPE> Timer_Node<TYPE> *
Timer_List<TYPE>::get_first (void)
{
	return this->get_first_i();
}

template <class TYPE> Timer_Node<TYPE> *
Timer_List<TYPE>::get_first_i (void) const
{
	Timer_Node<TYPE>* first = this->head_->get_next();
	if (first != this->head_) // Note : is_empty() uses get_first()
		return first;
	return 0;
}


// Removes the first node on the list and returns it.

template <class TYPE> Timer_Node<TYPE> *
Timer_List<TYPE>::remove_first (void)
{
	Timer_Node<TYPE>* first = this->get_first();
	if (first != 0) {
		this->unlink(first);
		return first;
	}
	return 0;
}

#endif//_TIMER_LIST_CPP_